<?php


namespace App\Service;


class Curl
{

    protected $_options = [];     //

    public function __construct()
    {
    }


    // 请求地址
    public function url($url)
    {
        $this->_options['url'] = $url;

        return $this;
    }

    // 上传的文件夹
    public function file($file)
    {
        $this->_options['file'] = $file;

        return $this;
    }

    // 请求数据
    public function post($post)
    {
        $this->_options['post'] = $post;

        return $this;
    }

    // 请求数据
    public function json($json)
    {
        $this->_options['json'] = $json;

        return $this;
    }

    // 请求数据
    public function get($post)
    {
        $this->_options['get'] = $post;

        return $this;
    }

    // 请求头
    public function header($header)
    {
        $this->_options['header'] = $header;

        return $this;
    }

    // 请求头 在HTTP请求头中"Referer: "的内容
    public function refer($refer)
    {
        $this->_options['refer'] = $refer;

        return $this;
    }

    // 提交的$cookies 可以是cookie也可以是cookie文件
    public function cookie($cookie)
    {
        $this->_options['cookie'] = $cookie;

        return $this;
    }

    // 是否返回$cookies
    public function returnHeader($returnHeader)
    {
        $this->_options['returnHeader'] = $returnHeader;

        return $this;
    }

    // 设置代理  $proxy = '127.0.0.1:8080'; // 这里设置代理 IP
    public function proxy($proxy)
    {
        $this->_options['proxy'] = $proxy;

        return $this;
    }


    // 请求
    public function request($url = '')
    {
        // 参数
        $refer        = $this->getOption('refer');
        $header       = $this->getOption('header');
        $post         = $this->getOption('post');
        $json         = $this->getOption('json');
        $get          = $this->getOption('get');
        $cookie       = $this->getOption('cookie');
        $returnHeader = $this->getOption('returnHeader');
        $file         = $this->getOption('file');
        $proxy        = $this->getOption('proxy');
        if(empty($url)){
            $url = $this->getOption('url');
        }
        // 判断
        if(empty($url)){
            return false;
        }
        if(!file_exists($file)){
            $file = false;
        }
        if(empty($refer)){
            $urlArr = parse_url($url);
            $scheme = $urlArr['scheme'];
            $host   = $urlArr['host'];
            $refer  = $scheme.'://'.$host;
        }
        // 判断
        if(empty($url)){
            return false;
        }
        if($get){
            $url = $url.'?'.http_build_query($get);
        }

        // 重新赋值  避免下次又被使用
        $this->_options = [];
        // 执行
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)');
        //curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36');
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
        if($refer){
            curl_setopt($curl, CURLOPT_REFERER, $refer);
        }
        if($header){
            curl_setopt($curl, CURLOPT_HTTPHEADER, $header); // 传递头部信息
        }
        // 设置代理
        if($proxy){
            //$proxy = '127.0.0.1:8080'; // 这里设置代理 IP
            curl_setopt($curl, CURLOPT_PROXY, $proxy);
        }
        # 检测请求版本 发送文件
        if($file){
            if(class_exists('\CURLFile')){
                curl_setopt($curl, CURLOPT_SAFE_UPLOAD, true);
                //$data = array('Json' => $json, 'File' => new \CURLFile($new_path)); //>=5.5
                $post['file'] = new \CURLFile($file);
            } else{
                if(defined('CURLOPT_SAFE_UPLOAD')){
                    curl_setopt($curl, CURLOPT_SAFE_UPLOAD, false);
                }
                //$data = array('Json' => $json, 'File' => '@'.$new_path); //<=5.5
                $post['file'] = '@'.$file;
            }
        }
        if($post){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post));
        }
        if($json){
            if(is_array($json)){
                $json = json_encode($json, JSON_UNESCAPED_UNICODE);
            }
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $json);
        }
        if($get){
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');
            //curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($get));
        }
        if($cookie){
            if(is_file($cookie)){
                curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie); // 包含cookie数据的文件名
            } else{
                curl_setopt($curl, CURLOPT_COOKIE, $cookie); // 设定HTTP请求中"Cookie: "部分的内容
            }
        }

        // CURLOPT_COOKIEJAR
        curl_setopt($curl, CURLOPT_HEADER, $returnHeader); //返回response头部信息
        curl_setopt($curl, CURLOPT_TIMEOUT, 60); // 设置cURL允许执行的最长秒数
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); //将curl_exec()获取的信息以文件流的形式返回，而不是直接输出

        // 证书检验 https 需要设置不检查证书，否则报错
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 0-不检查证书 1-检查证书
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // 0-不检查证书 1-检查证书公共名 2-匹配证书

        curl_setopt($curl, CURLOPT_FORBID_REUSE, false);
        curl_setopt($curl, CURLOPT_FRESH_CONNECT, false);

        $data = curl_exec($curl);

        ## 返回错误信息
        if(curl_errno($curl)){
            return curl_error($curl);
        }

        curl_close($curl);

        if($returnHeader){
            list($header, $body) = explode("\r\n\r\n", $data, 2);
            preg_match_all("/Set\-Cookie:([^;]*);/", $header, $matches);
            if(empty($matches[1][0])){
                $pos = strpos($data, '<html');
                if($pos !== false){
                    $header = substr($data, 0, $pos);
                    $body   = substr($data, $pos);
                }
            }

            preg_match_all("/Set\-Cookie:([^;]*);/", $header, $matches);
            if($matches[1]){
                $info['cookie']  = substr($matches[1][0], 1);
                $info['cookies'] = $matches[1];
                $info['content'] = $body;
            } else{
                $info['cookie']  = '';
                $info['cookies'] = [];
                $info['content'] = $body;
            }


            return $info;
        } else{
            return $data;
        }
    }


    ##########################################################################################################

    /**
     * get请求
     * @param $url
     */
    function curl_get($url, $gzip = false, $firefox = false)
    {
        if($firefox){
            //火狐浏览器
            $useragent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0';
        } else{
            //谷歌浏览器
            $useragent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36';
        }
        $header  = $this->FormatHeader($url, $useragent);
        $timeout = 120;
        $ch      = curl_init($url);
        curl_setopt($ch, CURLOPT_FAILONERROR, true);
        //设置请求头信息
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        //不取得返回头信息
        curl_setopt($ch, CURLOPT_HEADER, 0);
        if($gzip){
            //解释gzip加密压缩
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept-Encoding: gzip, deflate'));
            curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
        }
        // 关闭https验证
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_ENCODING, "");
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_AUTOREFERER, true);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
        curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
        $content = curl_exec($ch);
        curl_close($ch);

        return $content;
    }

    //添加请求头
    function FormatHeader($url, $useragent)
    {
        // 解析url
        $temp   = parse_url($url);
        $query  = isset($temp['query']) ? $temp['query'] : '';
        $path   = isset($temp['path']) ? $temp['path'] : '/';
        $header = array(
            "GET {$path}?{$query} HTTP/1.1",
            "Host: {$temp['host']}",
            "Referer: http://{$temp['host']}/",
            "Content-Type: text/xml; charset=utf-8",
            'Accept: application/json, text/javascript, */*; q=0.01',
            'Accept-Encoding:gzip, deflate, br',
            'Accept-Language:zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
            'Connection:keep-alive',
            'X-Requested-With: XMLHttpRequest',
            'User-Agent: '.$useragent,
        );

        return $header;
    }

    ##########################################################################################################

    /**
     * 发起网络请求函数
     * @param String $url 请求的URL
     * @param bool $params 请求的参数内容
     * @param int $isPost 是否POST请求
     * @return bool|string  返回内容
     */
    function httpRequest($url, $params = false, $isPost = 0)
    {
        $httpInfo = [];
        $ch       = curl_init();

        if($isPost){
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
        } else{
            if($params){
                curl_setopt($ch, CURLOPT_URL, $url.'?'.$params);
            } else{
                curl_setopt($ch, CURLOPT_URL, $url);
            }
        }
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36');
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
        curl_setopt($ch, CURLOPT_TIMEOUT, 12);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        $reponse = curl_exec($ch);
        if($reponse === false){
            // echo "cURL Error: ".curl_error($ch);
            return false;
        }
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $httpInfo = array_merge($httpInfo, curl_getinfo($ch));
        curl_close($ch);

        return $reponse;
    }

    ##########################################################################################################

    /**
     * 字符串 剪切
     * @param $html  字符串
     * @param $start  开始的字符串
     * @param $end   结束的字符串
     * @return bool|string
     */
    public function cut_str($html, $start, $end = '')
    {
        $sPos   = strpos($html, $start) + strlen($start);
        $string = substr($html, $sPos); // 截取新的字符串

        // 如果没有结尾的字符串
        if(!$end){
            return $string;
        }

        // 如果有结尾的字符串
        $ePos   = strpos($string, $end);
        $result = substr($string, 0, $ePos);
        //$len    = $ePos - $sPos;
        //$result = substr($html, $sPos, $len);

        return $result;
    }


    ##########################################################################################################
    ## 获取参数
    protected function getOption($str)
    {
        return isset($this->_options[$str]) ? $this->_options[$str] : '';
    }


    ##########################################################################################################

    /****
     * @param string $url 访问的URL -- 同步
     * @param string $refer 在HTTP请求头中"Referer: "的内容
     * @param string $post post数据(不填则为GET)
     * @param string $cookie 提交的$cookies 可以是cookie也可以是cookie文件
     * @param array $header 设置一个你的浏览器agent的header 如：array('User-Agent: php test')
     * @param int $returnCookie 是否返回$cookies
     * @return bool|string
     */
    function curl_request($url, $post = [], $file = '', $refer = '', $cookie = '', $header = array(), $returnHeader = 0)
    {
        # 检测文件是否存在
        $new_path = $file;
        if(!file_exists($new_path)){
            $file = false;
        }

        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)');
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
        curl_setopt($curl, CURLOPT_REFERER, $refer);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header); // 传递头部信息


        # 检测请求版本 发送文件
        if($file){
            if(class_exists('\CURLFile')){
                curl_setopt($curl, CURLOPT_SAFE_UPLOAD, true);
                //$data = array('Json' => $json, 'File' => new \CURLFile($new_path)); //>=5.5
                $post['file'] = new \CURLFile($new_path);
            } else{
                if(defined('CURLOPT_SAFE_UPLOAD')){
                    curl_setopt($curl, CURLOPT_SAFE_UPLOAD, false);
                }
                //$data = array('Json' => $json, 'File' => '@'.$new_path); //<=5.5
                $post['file'] = '@'.$new_path;
            }
        }


        if($post){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post));
        }
        if($cookie){
            if(is_file($cookie)){
                curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie); // 包含cookie数据的文件名
            } else{
                curl_setopt($curl, CURLOPT_COOKIE, $cookie); // 设定HTTP请求中"Cookie: "部分的内容
            }
        }
        // CURLOPT_COOKIEJAR
        curl_setopt($curl, CURLOPT_HEADER, $returnHeader); //返回response头部信息
        curl_setopt($curl, CURLOPT_TIMEOUT, 10); // 设置cURL允许执行的最长秒数
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); //将curl_exec()获取的信息以文件流的形式返回，而不是直接输出


        // 证书检验 https 需要设置不检查证书，否则报错
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 0-不检查证书 1-检查证书
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); // 0-不检查证书 1-检查证书公共名 2-匹配证书
        $data = curl_exec($curl);

        ## 返回错误信息
        if(curl_errno($curl)){
            return curl_error($curl);
        }

        curl_close($curl);


        if($returnHeader){
            list($header, $body) = explode("\r\n\r\n", $data, 2);
            preg_match_all("/Set\-Cookie:([^;]*);/", $header, $matches);
            $info['cookie']  = substr($matches[1][0], 1);
            $info['content'] = $body;

            return $info;
        } else{
            return $data;
        }
    }
}


## 构建post带参数转跳到某个页面
function postForm($url, $data = array())
{
    //循环拼接表单项
    $formItemString = '';
    if(!empty($data)){
        if(is_string($data)){
            $formItemString .= "<input name='data' type='text' value='{$data}'/>";
        } else{
            foreach($data as $key => $value){
                $formItemString .= "<input name='{$key}' type='text' value='{$value}'/>";
            }
        }
    }

    //echo $data . '<br>';
    //echo $url . '<br>';
    //构造表单并自动跳转
    $content = <<<EOF
<form style="display:none" name="submit_form" id="submit_form" action="{$url}" method="post">
{$formItemString}
</form>
<script type="text/javascript">
document.submit_form.submit();
</script>
EOF;

    //exit($content);
    echo $content;
    die;
}
